/**************************************************************************/
/*                                                                        */
/**************************************************************************/

package rpt.bd.cenario;

import java.awt.Color;
import java.awt.Component;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JRadioButton;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import rpt.lib.CCalendarioComboBox;
import rpt.lib.CCoresComboBox;

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

/**
 * Classe contendo os dados na memória carregados a partir
 * do banco de dados.
 * @author Roberto Plácido Teixeira - RPT Informática
 */

public class CCampoRegistroBd {

    private Object fValorCampoBd = null;
    private Object fValorAnteriorCampoBd = null;
    private Object fValorOriginalCampoBd = null;
    private CEstruturaCampoRegistroBd fEstruturaCampoRegistroBd = null;
    private CRegistroBd fRegistroBd = null;

    /**************************************************************************/
    /*                                                                        */
    /**************************************************************************/

    /**
     * Construtor da instância do campo do registro de dados do
     * banco de dados.
     * @param aRegistroBd Registro que contém o campo.
     * @param aEstruturaCampoRegistroBd Estrutura do campo.
     */

    public CCampoRegistroBd(
            final CRegistroBd aRegistroBd,
            final CEstruturaCampoRegistroBd aEstruturaCampoRegistroBd) {
        super();
        fRegistroBd = aRegistroBd;
        fEstruturaCampoRegistroBd = aEstruturaCampoRegistroBd;
    }

    /**************************************************************************/
    /*                                                                        */
    /**************************************************************************/

    /**
     * Construtor da instância do campo do registro de dados do
     * banco de dados.
     * @param aRegistroBd Instância do registro que contém o campo.
     * @param aEstruturaCampoRegistroBd Instância contendo a estrutura do campo.
     * @param aRs RecordSet de dados recuperados do banco de dados
     * para armazenamento da instância na memória.
     */

    public CCampoRegistroBd(
            final CRegistroBd aRegistroBd,
            final CEstruturaCampoRegistroBd aEstruturaCampoRegistroBd,
            final ResultSet aRs) {
        this(aRegistroBd,aEstruturaCampoRegistroBd);
        if (aRs == null)
            fValorOriginalCampoBd = null;
        else
            fValorOriginalCampoBd = getValorCampoRs(aRs);
        fValorCampoBd = fValorOriginalCampoBd;
        fValorAnteriorCampoBd = fValorCampoBd;
    }

    /**************************************************************************/
    /*                                                                        */
    /**************************************************************************/

    /**
     * Construtor da instância do campo do registro de dados do
     * banco de dados.
     * @param aEstruturaCampoRegistroBd Instância contendo a estrutura do campo.
     * @param aValorCampoBd Valor atribuido ao campo.
     */

    public CCampoRegistroBd(
            final CEstruturaCampoRegistroBd aEstruturaCampoRegistroBd,
            final String aValorCampoBd) {
        super();
        fEstruturaCampoRegistroBd = aEstruturaCampoRegistroBd;
        fValorCampoBd = aValorCampoBd;
    }

    /**************************************************************************/
    /*                                                                        */
    /**************************************************************************/

    /**
     * Retorna a instância da classe de persistência de
     * informações no banco de dados à qual o campo está vinculada.
     * @return Instância da classe CPertinenciaBD do campo.
     */

    public CPersistenciaBd getPertinenciaBd() {
        return fRegistroBd.getPersistenciaBd();
    }
    

    /**************************************************************************/
    /*                                                                        */
    /**************************************************************************/

    /**
     * Retorna a instância da classe do registro do campo.
     * @return Instância da classe CRegistroBd do registro do campo.
     */

    public CRegistroBd getRegistroBd() {
        return fRegistroBd;
    }
    
    /**************************************************************************/
    /*                                                                        */
    /**************************************************************************/

    /**
     * Atribuição das cores de letra e de fundo do componente visual
     * vinculado ao campo e utilizado para apresentação e edição do
     * valor do campo.
     */
    
    public final void setCores() {
       EStatusOperacao so = getPertinenciaBd().getStatusOperacao();
       final boolean vEditar = ((so == EStatusOperacao.inclusao) || (so == EStatusOperacao.alteracao));
       fEstruturaCampoRegistroBd.setCores(vEditar,getIgualOriginal());
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    /**
     * retorna a avaliação dos valores original e editado do campo.
     * @return true se os valores são iguais, false se são diferentes.
     */
    
    public final boolean getIgualOriginal() {
        if (fValorCampoBd == null)
            if (fValorOriginalCampoBd == null)
                return true;
            else
                return fValorOriginalCampoBd.toString().equals("");
        else
            if (fValorOriginalCampoBd == null)
                return fValorCampoBd.toString().equals("");
            else
                return fValorCampoBd.toString().equals(fValorOriginalCampoBd.toString());
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    /**
     * retorna a avaliação dos valores original e editado do campo.
     * @return true se os valores são iguais, false se são diferentes.
     */
    
    public final boolean getIgualAnterior() {
        if (fValorCampoBd == null)
            if (fValorAnteriorCampoBd == null)
                return true;
            else
                return fValorAnteriorCampoBd.toString().equals("");
        else
            if (fValorAnteriorCampoBd == null)
                return fValorCampoBd.toString().equals("");
            else
                return fValorCampoBd.toString().equals(fValorAnteriorCampoBd.toString());
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    /**
     * Retorna a instância da classe com a estrutura do campo
     * contendo informações como tipo, componente visual,
     * entre outras.
     * @return Instância da classe CEstruturaCampoRegistroBd do campo.
     */

    public final CEstruturaCampoRegistroBd getEstruturaCampoRegistroBd() {
        return fEstruturaCampoRegistroBd;
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    public final Object getValorCampoRs(
            final ResultSet aRs) {
/*
        int vNumLinhas = 0;
        try {
            vNumLinhas = aRs.getFetchSize();
        } catch (SQLException ex) {
            vNumLinhas = 0;
            Logger.getLogger(CCampoRegistroBd.class.getName()).log(Level.SEVERE, null, ex);
        }
        if ((aRs == null) || (vNumLinhas <= 0)) return null;
 */
        Object vValorCampoRs = null;
        final String vNomeCampo = fEstruturaCampoRegistroBd.getNomeBd();
        if ((vNomeCampo == null) || (vNomeCampo.trim().equals(""))) return null;
        try {
            if (aRs.findColumn(vNomeCampo) < 0) {
                return null;
            }
        } catch (SQLException ex) {
            return null;
        }
        try {
            switch (fEstruturaCampoRegistroBd.getTipoCampo()) {
                case cor: {
                    if (aRs == null)
                        vValorCampoRs = new Color(0);
                    else
                        vValorCampoRs = new Color(aRs.getInt(vNomeCampo));
                    break;
                }
                case inteiro: {
                    if (aRs == null)
                        vValorCampoRs = new Integer(0);
                    else
                        vValorCampoRs = aRs.getInt(vNomeCampo);
                    break;
                }
                case decimal: {
                    if (aRs == null)
                        vValorCampoRs = new BigDecimal(0);
                    else
                        vValorCampoRs = aRs.getBigDecimal(vNomeCampo);
                    break;
                }
                case texto: {
                    if (aRs == null)
                        vValorCampoRs = aRs.getString("");
                    else
                        vValorCampoRs = aRs.getString(vNomeCampo);
                    break;
                }
                case data: {
                    Date d = null;
                    if (aRs != null)
                        try {
                            d = aRs.getDate(vNomeCampo);
                        } catch(Exception ex) {
                            d = null;
                        }
                    if (d == null)
                        vValorCampoRs = null;
                    else
                        vValorCampoRs = new SimpleDateFormat("dd/MM/yyyy").format(d);
                    break;
                }
                case hora: {
                    if (aRs == null)
                        vValorCampoRs = null;
                    else
                        try {
                            vValorCampoRs = aRs.getTime(vNomeCampo);
                        } catch(Exception ex) {
                            vValorCampoRs = null;
                        }
/*
                    if (d == null)
                        vValorCampoRs = null;
                    else
                        //vValorCampoRs = d;
                        vValorCampoRs = new SimpleDateFormat("HH:mm:ss").format(d);
*/
                    break;
                }
                case datahora: {
                    Date d = null;
                    if (aRs != null)
                        try {
                            d = aRs.getDate(vNomeCampo);
                        } catch(Exception ex) {
                            d = null;
                        }
                    if (d == null)
                        vValorCampoRs = "";
                    else
                        vValorCampoRs = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(d);
                    break;
                }
                case logico: {
                    if (aRs == null)
                        vValorCampoRs = false;
                    else
                        vValorCampoRs = aRs.getBoolean(vNomeCampo);
                    break;
                }
                default: {
                    if (aRs == null)
                        vValorCampoRs = "";
                    else
                        vValorCampoRs = aRs.getString(vNomeCampo);
                    break;
                }
            }
        } catch (SQLException ex) {
            final String vMensagem = ex.getMessage();
            vValorCampoRs = null; // "<erro:" + vMensagem + ">";
            try {
                vValorCampoRs = aRs.getString(1);
            } catch (SQLException ex1) {
                Logger.getLogger(CCampoRegistroBd.class.getName()).log(Level.SEVERE, null, ex1);
            }
            Logger.getLogger(CCampoRegistroBd.class.getName()).log(Level.SEVERE, null, ex);
        }
        return vValorCampoRs;
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    protected final void eventoAntesAtribuicaoValor() {
        fEstruturaCampoRegistroBd.eventoAntesAtribuicaoValor(this);
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    protected final void eventoDepoisAtribuicaoValor() {
        fEstruturaCampoRegistroBd.eventoDepoisAtribuicaoValor(this);
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    public final void setValorCampoBd(
            final Object aValorCampo) {
        if ((aValorCampo != null) && 
                (this.fValorAnteriorCampoBd != null) && 
                (this.fValorAnteriorCampoBd.toString().equals(aValorCampo.toString()))) {
            return;
        }
        eventoAntesAtribuicaoValor();
//      fValorCampoBd = aValorCampo;
        if (aValorCampo == null) {
            fValorCampoBd = null;
        }
        else {
            try {
                switch (fEstruturaCampoRegistroBd.getTipoCampo()) {
                    case cor: {
                        fValorCampoBd = (Color)aValorCampo;
                        break;
                    }
                    case inteiro: {
                        fValorCampoBd = new Integer(aValorCampo.toString());
                        break;
                    }
                    case decimal: {
                        BigDecimal bd = new BigDecimal(aValorCampo.toString());
                        fValorCampoBd = bd;
                        break;
                    }
                    case texto: {
                        fValorCampoBd = (String)aValorCampo;
                        break;
                    }
                    case data: {
                        if (aValorCampo instanceof Date)
                            fValorCampoBd = (Date)aValorCampo;
                        else
                            fValorCampoBd = (String)aValorCampo;
                        break;
                    }
                    case hora: {
                        if (aValorCampo instanceof Date)
                            fValorCampoBd = (Date)aValorCampo;
                        else
                            fValorCampoBd = (String)aValorCampo;
                        break;
                    }
                    case datahora: {
                        if (aValorCampo instanceof Date)
                            fValorCampoBd = (Date)aValorCampo;
                        else
                            fValorCampoBd = (String)aValorCampo;
                        break;
                    }
                    case logico: {
                        fValorCampoBd = (Boolean)aValorCampo;
                        break;
                    }
                    default: {
                        fValorCampoBd = aValorCampo;
                        break;
                   }
                }
            } catch (Exception ex) {
                final String vMensagem = ex.getMessage();
                Logger.getLogger(CCampoRegistroBd.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        setAtualizarFundo();
        eventoDepoisAtribuicaoValor();
        fValorAnteriorCampoBd = fValorCampoBd;
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    public final int setValorCampoBd(
            final Object aValor,
            final boolean aAtualizarComponente) {
        setValorCampoBd(aValor);
        if (aAtualizarComponente) {
            setValorComponente(fValorCampoBd);
        }
        return 1;
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    public final void setAtualizarFundo() {
        final Component vComponente = getEstruturaCampoRegistroBd().getComponente();
        if (getIgualOriginal()) {
            vComponente.setBackground(new Color(255,255,255));
            vComponente.setForeground(new Color(0,0,0));
        }
        else {
            vComponente.setBackground(new Color(255,192,192));
            vComponente.setForeground(new Color(0,0,0));
        }
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    public final int setValorComponente(
            final Object aValor) {
        //if (aValor == null) return -1;
        final Component c = fEstruturaCampoRegistroBd.getComponente();
        fEstruturaCampoRegistroBd.setValorComponente(aValor);
/*
        if (c == null) return -1;
        if (c instanceof JTextArea) {
            ((JTextArea)c).setText(fEstruturaCampoRegistroBd.getObjectStr(aValor));
            return 1;
        }
        if (c instanceof JFormattedTextField) {
            ((JFormattedTextField)c).setValue(aValor);
            return 1;
        }
        if (c instanceof JTextField) {
            ((JTextField)c).setText(fEstruturaCampoRegistroBd.getObjectStr(aValor));
            return 1;
        }
        if (c instanceof CCalendarioComboBox) {
            final CCalendarioComboBox ccb = (CCalendarioComboBox)c;
            boolean vEditavel = ccb.isEditable();
            ccb.setEditable(true);
            ccb.setSelectedItem(aValor);
            ccb.setEditable(vEditavel);
            return 1;
        }
        if (c instanceof CCoresComboBox) {
            final CCoresComboBox ccb = (CCoresComboBox)c;
            ccb.setSelectedItem(aValor);
            return 1;
        }
        if (c instanceof JComboBox) {
            final JComboBox cbx = (JComboBox)c;
            final int idx = cbx.getSelectedIndex();
            final Object o = cbx.getItemAt(idx);
            //String s = cbx.get
            return fEstruturaCampoRegistroBd.setValorComboBox(aValor);
        }
        if (c instanceof JCheckBox) {
            final JCheckBox cb = (JCheckBox)c;
            if (aValor instanceof Boolean)
                cb.setSelected((Boolean)aValor);
            else
                cb.setSelected(false);
            return 1;
        }
        if (c instanceof JRadioButton) {
            final JRadioButton rb = (JRadioButton)c;
            if (aValor instanceof Boolean)
                rb.setSelected((Boolean)aValor);
            else
                rb.setSelected(false);
            return 1;
        }
        if (c instanceof JSpinner) {
            final JSpinner rb = (JSpinner)c;
            if (aValor instanceof Integer)
                rb.setValue((Integer)aValor);
            else
                rb.setValue(new Integer(1));
            return 1;
        }
*/
        return 0;
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    public final Object getValorComponente() {
        final CEstruturaCampoRegistroBd e = getEstruturaCampoRegistroBd();
        Component c = e.getComponente();
        if (c == null)
            return null;
        if (c instanceof JTextArea)
            return ((JTextArea)c).getText();
        if (c instanceof JFormattedTextField) {
            final JFormattedTextField ftf = (JFormattedTextField)c;
            try {
                ftf.commitEdit();
            } catch (ParseException ex) {
                Logger.getLogger(CCampoRegistroBd.class.getName()).log(Level.SEVERE, null, ex);
            }
            return ftf.getValue();
        }
        if (c instanceof JTextField)
            return ((JTextField)c).getText();
        if (c instanceof CCalendarioComboBox) {
            final CCalendarioComboBox cbx = (CCalendarioComboBox)c;
            Object o = cbx.getModel().getSelectedItem();
            o = cbx.getComponenteTextoFormatado().getValue();
            return o;
        }
        if (c instanceof CCoresComboBox) {
            final Object o = ((CCoresComboBox)c).getModel().getSelectedItem();
            return o;
        }
        if (c instanceof JComboBox) {
            final Object o = ((JComboBox)c).getModel().getSelectedItem();
            return o;
        }
        if (c instanceof JCheckBox) {
            JCheckBox cb = (JCheckBox)c;
            final Object o = cb.isSelected();
            return o;
        }
        if (c instanceof JRadioButton) {
            JRadioButton rb = (JRadioButton)c;
            final Object o = rb.isSelected();
            return o;
        }
        if (c instanceof JSpinner) {
            JSpinner s = (JSpinner)c;
            final Object o = s.getValue();
            return o;
        }
/*
        if (c instanceof JRadioButton) {
            JRadioButton j = (JRadioButton)c;
            Object o = null; // j; // .getModel().get; // .getv.getModel().get'.getSelectedItem();
            return o;
        }
 */
        return "???";
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    public final void setValorOriginalCampo(
            final boolean aRestaurarOriginal) {
        if (aRestaurarOriginal)
            fValorCampoBd = fValorOriginalCampoBd;
        else
            fValorOriginalCampoBd = fValorCampoBd;
        setValorComponente(fValorCampoBd);
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    public final void setValorAnteriorCampo(
            final boolean aRestaurarOriginal) {
        if (aRestaurarOriginal)
            fValorCampoBd = fValorAnteriorCampoBd;
        else
            fValorAnteriorCampoBd = fValorCampoBd;
        setValorComponente(fValorCampoBd);
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    public final Object getValorCampoBd() {
        return fValorCampoBd;
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    public final String getValorComponenteCampoBdStr() {
        final Object o = getValorComponente();
        if (o == null)
            return null;
        else
            return o.toString();
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    public final String getValorCampoBdStr() {
        String vValorCampoBdStr = null;
        final CEstruturaCampoRegistroBd e = getEstruturaCampoRegistroBd();
        if (e instanceof CEstruturaCampoRegistroBdLookup) {
            final CEstruturaCampoRegistroBdLookup el = (CEstruturaCampoRegistroBdLookup)e;
            final Component c = el.getComponente();
            if (c instanceof JComboBox) {
                Object vValorCampoBd = null;
                if (fValorCampoBd == null)
                    vValorCampoBd = "0";
                else
                    vValorCampoBd = fValorCampoBd;
                final ComboBoxModel m = ((JComboBox)c).getModel();
                CRegistroBd vLocalizado = null;
                final int vNumItems = m.getSize();
                for (int vContador = 0; ((vContador < vNumItems) && (vLocalizado == null)); vContador++) {
                    final CRegistroBd r = (CRegistroBd)m.getElementAt(vContador);
                    final CCampoRegistroBd cr = r.getCampoRegistroBdChavePrimaria();
                    if ((cr != null) && (cr.getValorCampoBd() != null)) {
                        if (cr.toString().equals(vValorCampoBd.toString())) {
                            vValorCampoBdStr = cr.toString();
                            vLocalizado = r;
                        }
                    }
                }
            }
            else
                vValorCampoBdStr = getValorComponenteCampoBdStr();
                //vValorCampoBdStr = el.getValorComponenteStr();
        }
        else
            if (fValorCampoBd == null) return null;
            switch (fEstruturaCampoRegistroBd.getTipoCampo()) {
                case cor: {
                    final Object o = getValorCampoBd();
                    if (o != null) {
                        Color c = (Color)o;
                        vValorCampoBdStr = new Integer(c.getRGB()).toString();
                    }
                    break;
                }
                case inteiro: {
                    final Integer vValor = (Integer)getValorCampoBd();
                    if (vValor == null)
                        vValorCampoBdStr = "null";
                    else
                        vValorCampoBdStr = Integer.toString(vValor);
                    break;
                }
                case decimal: {
                    final BigDecimal vValor = (BigDecimal)getValorCampoBd();
                    if (vValor == null)
                        vValorCampoBdStr = "null";
                    else
                        vValorCampoBdStr = vValor.toString();
                    break;
                }
                case texto: {
                    final String vValor = (String)getValorCampoBd();
                    if (vValor == null)
                        vValorCampoBdStr = "null";
                    else
                        vValorCampoBdStr = vValor;
                    break;
                }
                case data: {
                    Object vValor = getValorCampoBd();
                    if (vValor == null)
                        vValorCampoBdStr = "null";
                    else
                        if (vValor instanceof String)
                            vValorCampoBdStr = (String)vValor;
                        else
                            vValorCampoBdStr = new SimpleDateFormat("dd/MM/yyyy").format((Date)vValor);
                    break;
                }
                case hora: {
                    Object vValor = getValorCampoBd();
                    if (vValor == null)
                        vValorCampoBdStr = "null";
                    else
                        if (vValor instanceof String)
                            vValorCampoBdStr = (String)vValor;
                        else
                            vValorCampoBdStr = new SimpleDateFormat("HH:mm:ss").format((Date)vValor);
                    break;
                }
                case datahora: {
                    Object vValor = getValorCampoBd();
                    if (vValor == null)
                        vValorCampoBdStr = "null";
                    else
                        if (vValor instanceof String)
                            vValorCampoBdStr = (String)vValor;
                        else
                            vValorCampoBdStr = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format((Date)vValor);
                    break;
                }
                case logico: {
                    final Boolean vValor = (Boolean)getValorCampoBd();
                    if (vValor == null)
                        vValorCampoBdStr = "null";
                    else
                        vValorCampoBdStr = vValor.toString();
                    break;
                }
                default: {
                    vValorCampoBdStr = (String)getValorCampoBd();
                    break;
                }
            }
        return vValorCampoBdStr;
    }

    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

/*
    public void setValorCampoBdComponente() {
        setValorComponente(null);
//      fEstruturaCampoRegistroBd.setValorComponente(null);
    }
*/
    /**************************************************************************/
    /***                                                                    ***/
    /**************************************************************************/

    @Override
    public final String toString() {
        return getValorCampoBdStr();
    }
}
